#include "ioactionform.h"
#include "ui_ioactionform.h"
#include <QMessageBox>
#include <QDebug>
#include <QSerialPortInfo>
#include <QSettings>
#include <QTextCodec>
#include "MZ_VC3000H.h"
#include <Common/SysEnv.h>

PLCReadThread::PLCReadThread(QObject *parent) : QThread(parent)
{
}

void PLCReadThread::run()
{
    while (!m_stop) {
        // 读取所有输入信号 (DI1-DI8)
        for (int i = 1; i <= 8; i++) {
            int state = PCI::pci().getinput(i);
            emit inputStateChanged(i, state > 0);
        }
        msleep(50); // 每50ms读取一次
    }
}

void PLCReadThread::stop()
{
    m_stop = true;
    wait();
}

ioActionForm::ioActionForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ioActionForm),
    m_plcThread(nullptr)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::Window);
    this->setAttribute(Qt::WA_DeleteOnClose, false);
    this->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
    this->setWindowTitle(tr("IO Channel (PLC)"));

    readPLCConfig();
    // 初始化定时器
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &ioActionForm::onTimeout);
    m_isRunning = false;
    m_isOpen = false;
    // 连接DO索引变化信号
    connect(ui->cBox_3, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &ioActionForm::onDOIndexChanged);

    // 初始化显示第一个DO的值
    if (!m_do.isEmpty()) {
        ui->lineEdit->setText(QString::number(m_do[0]));
    }

    // 初始化PLC
    if(initPLC()){
        ui->textEdit->append("PLC initialization successful!");
        m_isOpen = true;
        SysEnv::instance().setModuleOk(SysEnv::PLC);
    }else{
        SysEnv::instance().setModuleBad(SysEnv::PLC);
    }
}

ioActionForm::~ioActionForm()
{
    closePLC();
    delete ui;
}

void ioActionForm::readPLCConfig()
{
    QString Path = "configs/configs.ini";
    QSettings iniRead(Path, QSettings::IniFormat);
    iniRead.setIniCodec(QTextCodec::codecForName("UTF_8"));

    QString comPort = iniRead.value("PLC/comPort").toString();
    QString outputType = iniRead.value("PLC/outputType").toString();

    for(int i=0;i<8;i++){
        QString strDO = QString("DO%1").arg(i+1);
        ui->cBox_3->addItem(strDO);
        QString outputDO = QString("PLC/DO%1").arg(i+1);
        m_do.append(iniRead.value(outputDO).toInt());
    }

    ui->cBox_1->addItem(comPort);
    ui->cBox_2->addItem(outputType);

    m_savedComPort = comPort;
    m_outputType = outputType;
}

void ioActionForm::savePLCConfig()
{
    if (ui->cBox_3->currentIndex() < 0)
    {
        QMessageBox::warning(this, tr("Warning"), tr("Please select a DO index!"));
        ui->cBox_3->setFocus();
        return;
    }

    QString msText = ui->lineEdit->text().trimmed();
    if (msText.isEmpty())
    {
        QMessageBox::warning(this, tr("Warning"), tr("Delay time cannot be empty!"));
        ui->lineEdit->setFocus();
        ui->lineEdit->selectAll();
        return;
    }

    bool ok = false;
    int nMs = msText.toInt(&ok);
    if (!ok || nMs < 0)
    {
        QMessageBox::warning(this, tr("Warning"), tr("Please enter a valid non-negative integer!"));
        ui->lineEdit->setFocus();
        ui->lineEdit->selectAll();
        return;
    }

    QString Path = "configs/configs.ini";
    QSettings iniWrite(Path, QSettings::IniFormat);
    iniWrite.setIniCodec(QTextCodec::codecForName("UTF-8"));

    int nDoIndex = ui->cBox_3->currentIndex();
    QString key = QString("PLC/DO%1").arg(nDoIndex + 1);
    iniWrite.setValue(key, nMs);
    m_do[nDoIndex] = nMs;
    iniWrite.sync();
    if(m_isOpen){
        int result = PCI::pci().setOutputMode(nDoIndex + 1, false, nMs);
        if (result != 0) {
            qDebug() << QString("[ERROR] set DO%1 error:%2").arg(nDoIndex + 1).arg(result);
        } else {
            qDebug() << QString("[INFO] set DO%1 success").arg(nDoIndex + 1);
        }
    }

    QMessageBox::information(this, tr("Information"), tr("Saved successfully!"));
}

void ioActionForm::populateCOMPorts()
{
    ui->cBox_1->clear();

    // 获取可用串口
    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &port : ports) {
        ui->cBox_1->addItem(port.portName());
    }
}

bool ioActionForm::initPLC()
{
    // 初始化VC3000H系统
    if (PCI::pci().InitialSystem() != 0) {
        qDebug() << "Error: Failed to initialize VC3000H system!";
        ui->textEdit->append("Error: Failed to initialize VC3000H system!");
        return false;
    }

    // 打开串口
    QString portName = ui->cBox_1->currentText();
    if (PCI::pci().openseral(portName.toStdString().c_str()) != 0) {
        qDebug() << "Error: Failed to open serial port!";
        ui->textEdit->append("Error: Failed to open serial port!");
        ui->Bt_clear->setEnabled(false);
        ui->Bt_get->setEnabled(false);
        ui->Bt_start->setEnabled(false);
        return false;
    }


    // 设置PNP模式
    QString mode = ui->cBox_2->currentText();
    if (PCI::pci().setPNP(0, mode.toStdString().c_str()) != 0) {
        QString info = QString("Error: Failed to set %1 mode!").arg(mode);
        qDebug() << info;
        ui->textEdit->append(info);
        return false;
    }



    // QList<int> chn ={1,2 ,4 ,8 ,16, 32, 64, 128};
    // for (int idx = 0; idx < 8; idx++) {
    //    int result = PCI::pci().setOutputMode(chn[idx], false, m_do[idx]);
    //    if (result != 0) {
    //        qDebug() << QString("[ERROR] set DO%1 error:%2").arg(chn[idx]).arg(result);
    //    } else {
    //        qDebug() << QString("[INFO] set DO%1 success").arg(chn[idx]);
    //    }
    // }

    return true;
}

void ioActionForm::closePLC()
{
    if (m_plcThread) {
        m_plcThread->stop();
        delete m_plcThread;
        m_plcThread = nullptr;
    }
    PCI::pci().Destroy();
}

void ioActionForm::onInputStateChanged(int inputPort, bool state)
{
    // 更新UI显示输入状态
    switch (inputPort) {
    case 1: ui->label_44->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 2: ui->label_45->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 3: ui->label_46->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 4: ui->label_47->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 5: ui->label_48->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 6: ui->label_49->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 7: ui->label_50->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    case 8: ui->label_51->setStyleSheet(state ? "color: green;" : "color: red;"); break;
    default: break;
    }
}




void ioActionForm::onComPortChanged(int index)
{
    // 关闭当前PLC连接
    closePLC();

    // 重新初始化PLC
    initPLC();
}

void ioActionForm::slotFrameInfo(const CFrameResult &data)
{
    int result = 0;
    QList<int> chn ={1,2 ,4 ,8 ,16, 32, 64, 128};
    switch (data.camera) {
    case 1:
        if(data.result){ //CCD1NG
            result = PCI::pci().setoutput(chn[0], true);
            // result = PCI::pci().setOutputMode(chn[2], true, m_do[2]);
        }else{          //CCD1OK
            result = PCI::pci().setoutput(chn[2], true);
            // result = PCI::pci().setOutputMode(chn[0], true, m_do[0]);
        }
        break;
    case 2:
        if(data.result){//CCD2NG
            result = PCI::pci().setoutput(chn[1], true);
            // result = PCI::pci().setOutputMode(chn[3], true, m_do[3]);
        }else{         //CCD2OK
            result = PCI::pci().setoutput(chn[3], true);
            // result = PCI::pci().setOutputMode(chn[1], true, m_do[1]);
        }
        break;
    default:
        break;
    }
    qDebug() << "ioActionForm::slotFrameInfo:" << data.camera << data.result;
    //发送 运行信号
    result = PCI::pci().setoutput(chn[7], true);

    //同步信号
    result = PCI::pci().getinput(chn[0]);
    result = PCI::pci().getinput(chn[1]);

    // 清除指令
    int DiResult = PCI::pci().getinput(chn[2]);
    if(DiResult){
        qDebug() << "data clear";
        emit clearDataRequested();
    }
}

void ioActionForm::onDOIndexChanged(int index)
{
    if (index >= 0 && index < m_do.size()) {
        ui->lineEdit->setText(QString::number(m_do[index]));
    }
}

void ioActionForm::onTimeout()
{
    // 只发送勾选的输出
    QList<int> chn ={1,2 ,4 ,8 ,16, 32, 64, 128};
    for (int i = 0; i < 8; i++) {
        QCheckBox *checkBox = findChild<QCheckBox*>(QString("checkBox_%1").arg(i + 9));
        if (checkBox && checkBox->isChecked()) {
            int result = PCI::pci().setoutput(chn[i], true);
            ui->textEdit->append(QString("DO%1 set to true, result: %2")
                                     .arg(i+1)
                                     .arg(result));
        }
    }
}

void ioActionForm::on_Bt_get_clicked()
{
    ui->textEdit->append(tr("Getting IO levels..."));
    for (int i = 1; i <= 8; i++) {
        int state = PCI::pci().getinput(i);
        onInputStateChanged(i, state);
        ui->textEdit->append(QString(tr("DI%1: %2")).arg(i).arg(state ? tr("HIGH") : tr("LOW")));
    }
}


void ioActionForm::on_Bt_start_clicked()
{
    if (!m_isRunning) {
        // Start loop
        m_timer->start(1000); // Trigger every second
        m_isRunning = true;
        ui->Bt_start->setText(tr("Stop Execution"));
        ui->textEdit->append(tr("Started loop execution..."));
    } else {
        // Stop loop
        m_timer->stop();
        m_isRunning = false;
        ui->Bt_start->setText(tr("Start Execution"));
        ui->textEdit->append(tr("Stopped execution"));
    }
}


void ioActionForm::on_Bt_clear_clicked()
{
    ui->textEdit->clear();
    ui->textEdit->append(tr("Text cleared"));
}


void ioActionForm::on_Bt_save_clicked()
{
    savePLCConfig();
    int nDoIndex = ui->cBox_3->currentIndex();
    if (nDoIndex >= 0 && nDoIndex < m_do.size()) {
        ui->lineEdit->setText(QString::number(m_do[nDoIndex]));
    }

}

